﻿//#include<iostream>
//#include<string>
//using namespace std;
////double Divide(int a, int b)
////{
////	try
////	{
////		// 当b == 0时抛出异常
////		if (b == 0)
////		{
////			string s("Divide by zero condition!");
////			throw s;
////		} 
////		else
////		{
////		return ((double)a / (double)b);
////		}
////	} 
////	catch(int errid)
////		{
////			cout << errid << endl;
////		} 
////	return 0;
////} 
////void Func()
////{
////	int len, time;
////	cin >> len >> time;
////	try
////	{
////		cout << Divide(len, time) << endl;
////	} 
////	catch(const char* errmsg)
////	{
////		cout << errmsg << endl;
////	} 
////	cout << __FUNCTION__ << ":" << __LINE__ << "行执行" << endl;
////} 
////int main()
////{
////	while (1)
////	{
////		try
////		{
////			Func();
////		} 
////		catch(const string & errmsg)
////		{
////			cout << errmsg << endl;
////		}
////	}
////	return 0;
////}
//
//
//#include<thread>
//// ⼀般⼤型项⽬程序才会使⽤异常，下⾯我们模拟设计⼀个服务的⼏个模块
//// 每个模块的继承都是Exception的派⽣类，每个模块可以添加⾃⼰的数据
//// 最后捕获时，我们捕获基类就可以
//class Exception
//{
//	public :
//	Exception(const string& errmsg, int id)
//		: _errmsg(errmsg)
//		, _id(id)
//	{}
//	virtual string what() const
//	{
//		return _errmsg;
//	} 
//	int getid() const
//	{
//		return _id;
//	}
//protected:
//	string _errmsg;
//	int _id;
//};
//class SqlException : public Exception
//{
//	public :
//	SqlException(const string& errmsg, int id, const string& sql)
//		: Exception(errmsg, id)
//		, _sql(sql)
//	{}
//	virtual string what() const
//	{
//		string str = "SqlException:";
//		str += _errmsg;
//		str += "->";
//		str += _sql;
//		return str;
//	}
//private:
//	const string _sql;
//};
//
//class CacheException : public Exception
//{
//	public :
//	CacheException(const string& errmsg, int id)
//		: Exception(errmsg, id)
//	{}
//	virtual string what() const
//	{
//		string str = "CacheException:";
//		str += _errmsg;
//		return str;
//	}
//};
//class HttpException : public Exception
//{
//	public :
//	HttpException(const string& errmsg, int id, const string& type)
//		: Exception(errmsg, id)
//		, _type(type)
//	{}
//	virtual string what() const
//	{
//		string str = "HttpException:";
//		str += _type;
//		str += ":";
//		str += _errmsg;
//		return str;
//	}
//private:
//	const string _type;
//};
//void SQLMgr()
//{
//	if (rand() % 7 == 0)
//	{
//		throw SqlException("权限不足", 100, "select * from name = '张三'");
//	} else
//	{
//	cout << "SQLMgr 调用成功" << endl;
//	}
//}
//
//void CacheMgr()
//{
//	if (rand() % 5 == 0)
//	{
//		throw CacheException("权限不足", 100);
//	} 
//	else if (rand() % 6 == 0)
//	{
//		throw CacheException("数据不存在", 101);
//	} 
//	else
//	{
//		cout << "CacheMgr 调用成功" << endl;
//	} 
//	SQLMgr();
//} 
//void HttpServer()
//{
//	if (rand() % 3 == 0)
//	{
//		throw HttpException("请求资源不存在", 100, "get");
//	} 
//	else if (rand() % 4 == 0)
//	{
//		throw HttpException("权限不足", 101, "post");
//	} 
//	else
//	{
//		cout << "HttpServer调用成功" << endl;
//	} 
//	CacheMgr();
//} 
////int main()
////{
////	srand(time(0));
////	while (1)
////	{
////		this_thread::sleep_for(chrono::seconds(1));
////		try {
////			HttpServer();
////		} catch(const Exception & e) // 这⾥捕获基类，基类对象和派⽣类对象都可以被捕获
////		{
////		cout << e.what() << endl;
////		} 
////		catch(...)
////		{
////			cout << "Unkown Exception" << endl;
////		}
////	} 
////	return 0;
////}
//
//
////// 下⾯程序模拟展⽰了聊天时发送消息，发送失败补货异常，但是可能在
////// 电梯地下室等场景⼿机信号不好，则需要多次尝试，如果多次尝试都发
////// 送不出去，则就需要捕获异常再重新抛出，其次如果不是⽹络差导致的
////// 错误，捕获后也要重新抛出。
////void _SeedMsg(const string& s)
////{
////	if (rand() % 2 == 0)
////	{
////		throw HttpException("⽹络不稳定，发送失败", 102, "put");
////	} 
////	else if (rand() % 7 == 0)
////	{
////		throw HttpException("你已经不是对象的好友，发送失败", 103, "put");
////	} 
////	else
////	{
////	cout << "发送成功" << endl;
////	}
////} 
////void SendMsg(const string& s)
////	{
////		// 发送消息失败，则再重试3次
////		for (size_t i = 0; i < 4; i++)
////		{
////			try
////			{
////				_SeedMsg(s);
////				break;
////			} 
////			catch(const Exception & e)
////			{
////				// 捕获异常，if中是102号错误，⽹络不稳定，则重新发送
////				// 捕获异常，else中不是102号错误，则将异常重新抛出
////				if (e.getid() == 102)
////				{
////					// 重试三次以后否失败了，则说明⽹络太差了，重新抛出异常
////					if (i == 3)
////						throw;
////					cout << "开始第" << i + 1 << "重试" << endl;
////				} 
////				else
////				{
////					throw;
////				}
////			}
////		}
////	} 
////	int main()
////	{
////		srand(time(0));
////		string str;
////		while (cin >> str)
////		{
////			try
////			{
////				SendMsg(str);
////			} 
////			catch(const Exception & e)
////			{
////				cout << e.what() << endl << endl;
////			} 
////			catch(...)
////			{
////				cout << "Unkown Exception" << endl;
////			}
////		} 
////		return 0;
////	}
//
//
//
////double Divide(int a, int b)
////{
////	// 当b == 0时抛出异常
////	if (b == 0)
////	{
////		throw "Division by zero condition!";
////	} 
////	return(double)a / (double)b;
////} 
////void Func()
////{
////	// 这⾥可以看到如果发⽣除0错误抛出异常，另外下⾯的array没有得到释放。
////	// 所以这⾥捕获异常后并不处理异常，异常还是交给外层处理，这⾥捕获了再
////	// 重新抛出去。
////	int* array = new int[10];
////	try
////	{
////		int len, time;
////		cin >> len >> time;
////		cout << Divide(len, time) << endl;
////	} 
////	catch(...)
////	{
////		// 捕获异常释放内存
////		cout << "delete []" << array << endl;
////		delete[] array;
////		throw; // 异常重新抛出，捕获到什么抛出什么
////	} 
////	cout << "delete []" << array << endl;
////	delete[] array;
////} 
////int main()
////{
////	try
////	{
////		Func();
////	} 
////	catch(const char* errmsg)
////	{
////		cout << errmsg << endl;
////	} 
////	catch(const exception & e)
////	{
////		cout << e.what() << endl;
////	} 
////	catch(...)
////	{
////		cout << "Unkown Exception" << endl;
////	} 
////	return 0;
////}
//
//
////// C++11
////size_type size() const noexcept;
////iterator begin() noexcept;
////const_iterator begin() const noexcept;
//double Divide(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		throw "Division by zero condition!";
//	} 
//	return(double)a / (double)b;
//} 
//int main()
//{
//	try
//	{
//		int len, time;
//		cin >> len >> time;
//		cout << Divide(len, time) << endl;
//	} 
//	catch(const char* errmsg)
//	{
//		//cout << errmsg << endl;
//	} 
//	catch(...)
//	{
//		cout << "Unkown Exception" << endl;
//	} 
//	int i = 0;
//	cout << noexcept(Divide(1, 2)) << endl;
//	cout << noexcept(Divide(1, 0)) << endl;
//	cout << noexcept(++i) << endl;
//	return 0;
//}




#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>
#include <limits>
#include <tuple>

// 节点结构体
struct Node {
    int index;
    double x, y, z;
};

// 面片结构体
struct Face {
    int index;
    std::vector<int> nodes; // 组成面片的节点序号
    int boundary_marker;
};

// Polygon 数据管理类
class PolygonData {
public:
    std::map<int, Node> nodes; // 存储节点
    std::map<int, Face> faces; // 存储面片

    // 计算三角形面积
    double calculateTriangleArea(const Node& a, const Node& b, const Node& c) {
        double abx = b.x - a.x, aby = b.y - a.y, abz = b.z - a.z;
        double acx = c.x - a.x, acy = c.y - a.y, acz = c.z - a.z;
        double cross_x = aby * acz - abz * acy;
        double cross_y = abz * acx - abx * acz;
        double cross_z = abx * acy - aby * acx;
        double area = 0.5 * std::sqrt(cross_x * cross_x + cross_y * cross_y + cross_z * cross_z);
        return area;
    }

    // 读取Polygon文件
    void readPolygonFile(const std::string& filePath) {
        std::ifstream file(filePath);
        if (!file.is_open()) {
            std::cerr << "Error: Unable to open file " << filePath << std::endl;
            return;
        }

        std::string line;
        std::getline(file, line); // 跳过第一行说明

        // 读取节点信息
        int nodeCount, dim, attrCount, boundaryMarker;
        file >> nodeCount >> dim >> attrCount >> boundaryMarker;
        for (int i = 0; i < nodeCount; ++i) {
            int index;
            double x, y, z;
            file >> index >> x >> y >> z;
            nodes[index] = { index, x, y, z };
        }

        // 读取面片信息
        int faceCount;
        file >> faceCount >> boundaryMarker;
        for (int i = 0; i < faceCount; ++i) {
            int faceIndex, marker, nodeCountInFace;
            file >> faceIndex >> marker >> nodeCountInFace;
            std::vector<int> faceNodes(nodeCountInFace);
            for (int j = 0; j < nodeCountInFace; ++j) {
                file >> faceNodes[j];
            }
            faces[faceIndex] = { faceIndex, faceNodes, marker };
        }

        file.close();
    }

    // 查询指定节点的坐标
    std::tuple<double, double, double> getNodeCoordinates(int nodeIndex) {
        if (nodes.find(nodeIndex) != nodes.end()) {
            return { nodes[nodeIndex].x, nodes[nodeIndex].y, nodes[nodeIndex].z };
        }
        return { 0.0, 0.0, 0.0 }; // 如果节点不存在，返回默认值
    }

    // 查询指定面片的组成节点坐标
    std::vector<std::tuple<double, double, double>> getFaceNodesCoordinates(int faceIndex) {
        std::vector<std::tuple<double, double, double>> coordinates;
        if (faces.find(faceIndex) != faces.end()) {
            for (int nodeIndex : faces[faceIndex].nodes) {
                if (nodes.find(nodeIndex) != nodes.end()) {
                    coordinates.push_back(getNodeCoordinates(nodeIndex));
                }
            }
        }
        return coordinates;
    }

    // 找出面积最大和最小的面片
    std::pair<int, int> findMinMaxAreaFaces() {
        int maxFaceIndex = -1, minFaceIndex = -1;
        double maxArea = -1.0, minArea = std::numeric_limits<double>::max();

        for (const auto& facePair : faces) {
            const Face& face = facePair.second;
            if (face.nodes.size() == 3) { // 只处理三角形面片
                const Node& a = nodes[face.nodes[0]];
                const Node& b = nodes[face.nodes[1]];
                const Node& c = nodes[face.nodes[2]];
                double area = calculateTriangleArea(a, b, c);
                if (area > maxArea) {
                    maxArea = area;
                    maxFaceIndex = face.index;
                }
                if (area < minArea) {
                    minArea = area;
                    minFaceIndex = face.index;
                }
            }
        }

        return { maxFaceIndex, minFaceIndex };
    }

    // 删除指定面片
    void deleteFace(int faceIndex) {
        faces.erase(faceIndex);
    }

    // 修改指定节点的坐标
    void modifyNodeCoordinates(int nodeIndex, double newX, double newY, double newZ) {
        if (nodes.find(nodeIndex) != nodes.end()) {
            nodes[nodeIndex].x = newX;
            nodes[nodeIndex].y = newY;
            nodes[nodeIndex].z = newZ;
        }
    }

    // 查询落在指定三维包围盒内的面片
    std::vector<int> queryFacesInBoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
        std::vector<int> result;
        for (const auto& facePair : faces) {
            const Face& face = facePair.second;
            bool inside = true;
            for (int nodeIndex : face.nodes) {
                const Node& node = nodes[nodeIndex];
                if (node.x < minX || node.x > maxX || node.y < minY || node.y > maxY || node.z < minZ || node.z > maxZ) {
                    inside = false;
                    break;
                }
            }
            if (inside) {
                result.push_back(face.index);
            }
        }
        return result;
    }

    // 输出修改后的Polygon文件
    void writePolygonFile(const std::string& filePath) {
        std::ofstream file(filePath);
        if (!file.is_open()) {
            std::cerr << "Error: Unable to create file " << filePath << std::endl;
            return;
        }

        file << "Modified polygon file\n";
        file << nodes.size() << " 3 0 0\n";
        for (const auto& nodePair : nodes) {
            const Node& node = nodePair.second;
            file << node.index << " " << node.x << " " << node.y << " " << node.z << "\n";
        }

        file << faces.size() << " 1\n";
        for (const auto& facePair : faces) {
            const Face& face = facePair.second;
            file << face.index << " " << face.boundary_marker << " ";
            for (int nodeIndex : face.nodes) {
                file << nodeIndex << " ";
            }
            file << "\n";
        }

        file.close();
    }
};

int main() {
    PolygonData polygon;
    std::string filename = "sumand02t.poly";

    // 读取 Polygon 文件
    polygon.readPolygonFile(filename);

    // 查询指定序号的节点坐标
    int nodeIndex = 98;
    auto nodeCoords = polygon.getNodeCoordinates(nodeIndex);
    std::cout << "Node " << nodeIndex << " coordinates: ("
        << std::get<0>(nodeCoords) << ", "
        << std::get<1>(nodeCoords) << ", "
        << std::get<2>(nodeCoords) << ")\n";

    // 查询指定 tin（face）序号的组成节点坐标
    int faceIndex = 1;
    auto faceNodeCoords = polygon.getFaceNodesCoordinates(faceIndex);
    std::cout << "Face " << faceIndex << " node coordinates:\n";
    for (const auto& coord : faceNodeCoords) {
        std::cout << "(" << std::get<0>(coord) << ", "
            << std::get<1>(coord) << ", "
            << std::get<2>(coord) << ")\n";
    }

    // 找出面积最大、最小的 face
    std::pair<int, int> result = polygon.findMinMaxAreaFaces();
    int maxFace = result.first;
    int minFace = result.second;
    std::cout << "Max area face index: " << maxFace << "\n";
    std::cout << "Min area face index: " << minFace << "\n";

    // 删除指定序号的 tin（face）
    int deleteFaceIndex = 53715; // 假设删除这个面片
    polygon.deleteFace(deleteFaceIndex);
    std::cout << "Deleted face " << deleteFaceIndex << "\n";

    // 修改某个节点的坐标值
    int modifyNodeIndex = 98;
    polygon.modifyNodeCoordinates(modifyNodeIndex, 10.0, 20.0, 30.0);
    std::cout << "Modified node " << modifyNodeIndex << " to (10.0, 20.0, 30.0)\n";

    // 查询落在指定三维包围盒内的 tin（face）的序号列表
    double minX = 0.0, minY = 0.0, minZ = 0.0;
    double maxX = 100.0, maxY = 100.0, maxZ = 100.0;
    auto facesInBox = polygon.queryFacesInBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
    std::cout << "Faces in bounding box:\n";
    for (int faceIdx : facesInBox) {
        std::cout << faceIdx << " ";
    }
    std::cout << "\n";

    // 输出修改后的 polygon 文件
    std::string outputFilename = "modified_polygon.poly";
    polygon.writePolygonFile(outputFilename);
    std::cout << "Modified polygon data written to " << outputFilename << "\n";

    return 0;
}